<template>
  <el-form
      ref="form"
      :rules="rules"
      :model="model"
      v-bind="$attrs"
      :validate-on-rule-change="false"
      v-if="model"
  >
    <template v-for="(item, index) in options" :key="index">
      <el-form-item v-if="!item.children || !item.children.length" :label="item.label" :prop="item.prop">
        <component
            v-if="item.type !== 'upload' && item.type !== 'editor'"
            v-bind="item.attrs"
            :is="`el-${item.type}`"
            v-model="model[item.prop]"
            :placeholder="item.placeholder"
        ></component>
        <el-upload
            v-model:file-list="model[item.prop]"
            v-bind="item.uploadAttrs"
            :on-preview="onPreview"
            :on-remove="onRemove"
            :on-success="onSuccess"
            :on-error="onError"
            :on-progress="onProgress"
            :on-change="onChange"
            :before-upload="beforeUpload"
            :before-remove="beforeRemove"
            :http-request="httpRequest"
            :on-exceed="onExceed"
            v-if="item.type === 'upload'"
        >
          <slot name="uploadArea"></slot>
          <template #tip>
            <div style="font-size: 12px">
              {{ item.attrs.tip }}
            </div>
          </template>
        </el-upload>
        <div v-if="item.type === 'editor'" id="editor">
        </div>
      </el-form-item>
      <el-form-item v-if="item.children && item.children.length" :label="item.label" :prop="item.prop">
        <component
            v-bind="item.attrs"
            :is="`el-${item.type}`"
            v-model="model[item.prop]"
            :placeholder="item.placeholder"
        >
          <component
              v-for="(citem, cindex) in item.children"
              :key="cindex"
              :label="citem.label"
              :value="citem.value"
              :is="`el-${citem.type}`"
          >
          </component>
        </component>
      </el-form-item>
    </template>
    <el-form-item>
      <slot name="action" :form="form" :model="model"></slot>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import {onMounted, PropType, ref, watch, nextTick} from "vue";
import {FormOptions, FormInstance} from "./types";
import cloneDeep from "lodash/cloneDeep";
import E from 'wangeditor'

let props = defineProps({
  options: {
    type: Array as PropType<FormOptions[]>,
    required: true
  }
})

let model = ref<any>(null)
let rules = ref<any>(null)
let form = ref<FormInstance | null>(null)
let edit = ref()

let initForm = () => {
  if (props.options && props.options.length) {
    let m: any = {}
    let r: any = {}
    props.options.map((item: FormOptions) => {
      m[item.prop!] = item.value
      r[item.prop!] = item.rules as any
      if (item.type === 'editor') {
        nextTick(() => {
          if (document.getElementById('editor')) {
            const editor = new E('#editor')
            editor.config.placeholder = ''
            editor.create()
            editor.txt.html(item.value)
            editor.config.onchange = (newHtml: string) => {
              model.value[item.prop!] = newHtml
            }
            edit.value = editor
          }
        })
      }
    })
    model.value = cloneDeep(m)
    rules.value = cloneDeep(r)
  }
}

onMounted(() => {
  initForm()
})

watch(() => props.options, value => {
  initForm()
}, {deep: true})

let emits = defineEmits(['onPreview',
  'onRemove', 'onSuccess', 'onError', 'onProgress',
  'onChange', 'beforeUpload', 'beforeRemove',
  'httpRequest', 'onExceed'])

let onPreview = (file: any) => {
  emits('onPreview', file)
}

let onRemove = (file: any, fileList: any) => {
  emits('onRemove', {file, fileList})
}

let onSuccess = (response: any, file: any, fileList: any) => {
  emits('onSuccess', {response, file, fileList})
}

let onError = (err: any, file: any, fileList: any) => {
  emits('onError', {err, file, fileList})
}

let onProgress = (event: any, file: any, fileList: any) => {
  emits('onProgress', {event, file, fileList})
}

let onChange = (file: any, fileList: any) => {
  emits('onChange', {file, fileList})
}

let beforeUpload = (file: any) => {
  emits('beforeUpload', file)
}

let beforeRemove = (file: any, fileList: any) => {
  emits('beforeRemove', {file, fileList})
}

let httpRequest = () => {
  emits('httpRequest')
}

let onExceed = (files: any, fileList: any) => {
  emits('onExceed', {files, fileList})
}
</script>

<style scoped>

</style>